﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Security.Principal;
using System.Diagnostics;
using Microsoft.Win32;
using System.ComponentModel;
using System.IO;
using RoketPack.IM;

namespace RoketPack
{
    static class Program
    {
        internal static Manager Manager = null;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            // Correct the working directory.
            Program.CorrectWorkingDirectory();

            // Set up visual styles and font rendering.
            Application.EnableVisualStyles();
            Application.VisualStyleState = System.Windows.Forms.VisualStyles.VisualStyleState.ClientAndNonClientAreasEnabled;
            Application.SetCompatibleTextRenderingDefault(false);

            // Ensure self-update takes place.
            if (SelfUpdate.IsUpdating())
            {
                SelfUpdate.Update();
                return;
            }
            else
                SelfUpdate.Cleanup();

            // Ensure association with the roket: protocol.
            if (Protocol.HandleAssociation(args))
                return;

            // Check for run-once configuration.
            if (!Program.RunOnceConfiguration())
                return;

            // Check for run-once configuration.
            if (RecoveryUtil.IsRequired())
            {
                if (!RecoveryUtil.Run())
                    return;
            }

            // Run the main application.
            try
            {
                Program.Manager = new Manager();
                Application.Run();
            }
            catch (ImmediateExitException)
            {
                // We've been told to immediately exit by the Manager's constructor.
            }
            catch (Exception ex)
            {
                Program.HandleUnhandledException(ex);
            }
        }

        internal static void HandleUnhandledException(Exception ex)
        {
            // Hide the system tray icon.
            if (Program.Manager != null)
                Program.Manager.SystemIconHide();

            // Unexpected application exception occurred.
            if (!RecoveryUtil.SaveRecoveryData(ex))
                MessageBox.Show("Unable to save recovery data to:\n" + RecoveryUtil.RecoveryDataPath);

            // Restart the application (it will launch in
            // recovery mode).
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.UseShellExecute = true;
            startInfo.WorkingDirectory = Environment.CurrentDirectory;
            startInfo.FileName = UNC.UniversalApplicationPath;
            try
            {
                Process p = Process.Start(startInfo);
            }
            catch (System.ComponentModel.Win32Exception)
            {
                MessageBox.Show("Unable to automatically restart RoketPack in recovery mode.");
            }
        }

        /// <summary>
        /// Handles the run-once configuration of RoketPack.
        /// </summary>
        /// <returns>Whether the application should exit because the configuration was abnormally closed.</returns>
        static bool RunOnceConfiguration()
        {
            if (!Protocol.IsAssociated() || !Certificate.IsInstalled())
            {
                ConfigurationWizard s = new ConfigurationWizard();
                if (s.ShowDialog() == DialogResult.Cancel)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Corrects the working directory so that it is currently set to where
        /// RoketPack.exe is installed (since the location it was run from is
        /// entirely irrelevant in the case of this software).
        /// </summary>
        internal static void CorrectWorkingDirectory()
        {
            string cl = Environment.CommandLine.Trim(' ');
            string app = "";
            if (cl[0] == '"')
            {
                int i = 1;
                while (i < cl.Length && cl[i] != '"')
                {
                    app += cl[i];
                    i++;
                }
            }
            else
            {
                if (cl.IndexOf(" ") == -1)
                    app = cl;
                else
                    app = cl.Split(' ')[0];
            }

            Directory.SetCurrentDirectory(Path.GetDirectoryName(app));
        }
    }
}
